namespace EyeOpen.Data
{
	using System.Configuration;
	using System.Data.Common;
	using System.Data.Entity;

	using EyeOpen.Domain;

	public abstract class EntityFrameworkUnitOfWork : DbContext, IUnitOfWork
	{
		protected EntityFrameworkUnitOfWork(ConnectionStringSettings connectionSettings)
			: this(connectionSettings.ProviderName, connectionSettings.ConnectionString)
		{
		}

		protected EntityFrameworkUnitOfWork(string connectionName)
			: base(connectionName)
		{
		}

		protected EntityFrameworkUnitOfWork(string providerName, string connectionString)
			: base(GetConnection(providerName, connectionString), true)
		{
		}

		public void Commit()
		{
			SaveChanges();
		}

		protected Repository<T> Repository<T>() where T : class, IEntity
		{
			return
				new Repository<T>(Set<T>(), Add, Delete, Update);
		}

		private static DbConnection GetConnection(string providerName, string connectionString)
		{
			var factory = DbProviderFactories.GetFactory(providerName);

			var connection = factory.CreateConnection();
			connection.ConnectionString = connectionString;

			return
				connection;
		}

		private void Add<T>(T obj) where T : class
		{
			Set<T>().Add(obj);
		}

		private void Delete<T>(T obj) where T : class
		{
			Set<T>().Remove(obj);
		}

		private void Update<T>(T obj) where T : class
		{
			Set<T>().Attach(obj);
			Entry(obj).State = System.Data.EntityState.Modified;
		}
	}
}